﻿using System;
using System.Collections.ObjectModel;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Channels;
using Prompts.Service.PromptService;
using Prompts.Service.ReportExecution;

// ReSharper disable CheckNamespace
namespace Prompts.Prompting.Model
// ReSharper restore CheckNamespace
{
    [DataContract(
        Name = "ParameterValueOrFieldReference", 
        Namespace = "http://schemas.datacontract.org/2004/07/Prompts.Service.ReportExecution")]
    [KnownTypeAttribute(typeof(ParameterValue))]
    public class ParameterValueOrFieldReference : object
    {
    }

    [ServiceContract(ConfigurationName = "Prompts.Prompting.Model.IChildPromptLevelService")]
    public interface IChildPromptLevelService
    {
        [OperationContractAttribute(
            AsyncPattern = true,
            Action = "http://tempuri.org/IChildPromptLevelService/GetChildren",
            ReplyAction = "http://tempuri.org/IChildPromptLevelService/GetChildrenResponse")]
        IAsyncResult BeginGetChildren(
            string promptName,
            string parameterName,
            ObservableCollection<ParameterValue> parameterValues,
            AsyncCallback callback,
            object asyncState);

        GetChildrenResponse EndGetChildren(IAsyncResult result);

        [OperationContractAttribute(
            AsyncPattern = true, 
            Action = "http://tempuri.org/IChildPromptLevelService/GetChildren2", 
            ReplyAction = "http://tempuri.org/IChildPromptLevelService/GetChildren2Response")]
        IAsyncResult BeginGetChildren2(
            string promptName, 
            string parameterName, 
            ParameterValue parameterValue, 
            AsyncCallback callback, 
            object asyncState);

        GetChildrenResponse EndGetChildren2(IAsyncResult result);


        [OperationContractAttribute(
            AsyncPattern = true,
            Action = "http://tempuri.org/IChildPromptLevelService/GetChildrenForRecursive",
            ReplyAction = "http://tempuri.org/IChildPromptLevelService/GetChildrenForRecursiveResponse")]
        IAsyncResult BeginGetChildrenForRecursive(
            string promptName,
            string parameterName,
            ParameterValue parameterValue,
            AsyncCallback callback,
            object asyncState);

        GetChildrenResponse EndGetChildrenForRecursive(IAsyncResult result);
    }

    public interface IChildPromptLevelServiceChannel : IChildPromptLevelService, IClientChannel
    {
    }

    public class ChildPromptLevelServiceClient 
        : ClientBase<IChildPromptLevelService>, IChildPromptLevelServiceClient
    {
        public ChildPromptLevelServiceClient(Binding binding, EndpointAddress remoteAddress) :
            base(binding, remoteAddress)
        {
        }

        public void GetChildrenAsync(
            string promptName,
            string parameterName,
            ObservableCollection<ParameterValue> parameterValues,
            Action<GetChildrenResponse> callback)
        {
            InvokeAsync(
                (inValues, callback1, asyncState) =>
                    {
                        var promptName1 = (string)inValues[0];
                        var parameterName1 = (string)inValues[1];
                        var parameterValues1 = (ObservableCollection<ParameterValue>)inValues[2];
                        var asyncResult = Channel.BeginGetChildren(
                            promptName1,
                            parameterName1,
                            parameterValues1,
                            callback1,
                            asyncState);
                        return asyncResult;
                    },
                new object[]
                    {
                        promptName,
                        parameterName,
                        parameterValues
                    },
                result =>
                    {
                        try
                        {
                            var retVal = Channel.EndGetChildren(result);
                            return new object[] { retVal };
                        }
                        catch (Exception exception)
                        {
                            var response = new GetChildrenResponse
                                {
                                    ErrorOccured = true,
                                    ErrorMessage = exception.Message
                                };
                            return new object[] {response};
                        }
                    },
                state =>
                    {
                        var args = (InvokeAsyncCompletedEventArgs)state;
                        callback((GetChildrenResponse) args.Results[0]);
                    },
                new object());
        }

        public void GetChildrenForRecursive(
            string promptName, 
            string parameterName, 
            ParameterValue parameterValue, 
            Action<GetChildrenResponse> callback)
        {
            InvokeAsync(
                (inValues, callback1, asyncState) =>
                    {
                        var promptName1 = (string)inValues[0];
                        var parameterName1 = (string)inValues[1];
                        var parameterValue1 = (ParameterValue)inValues[2];
                        return Channel.BeginGetChildrenForRecursive(
                            promptName1, 
                            parameterName1, 
                            parameterValue1, 
                            callback1, 
                            asyncState);
                    },
                new object[]
                    {
                        promptName,
                        parameterName,
                        parameterValue
                    },
                result =>
                    {
                        try
                        {
                            var retVal = Channel.EndGetChildrenForRecursive(result);
                            return new object[] { retVal };
                        }
                        catch (Exception exception)
                        {
                            var response = new GetChildrenResponse
                            {
                                ErrorOccured = true,
                                ErrorMessage = exception.Message
                            };
                            return new object[] { response };
                        }
                    },
                state =>
                    {
                        var args = (InvokeAsyncCompletedEventArgs)state;
                        callback((GetChildrenResponse)args.Results[0]);
                    },
                new object());
        }

        public void GetChildren2Async(
            string promptName,
            string parameterName,
            ParameterValue parameterValue,
            Action<GetChildrenResponse> callback)
        {
            InvokeAsync(
                (inValues, callback1, asyncState) =>
                {
                    var promptName1 = (string)inValues[0];
                    var parameterName1 = (string)inValues[1];
                    var parameterValue1 = (ParameterValue)inValues[2];
                    return Channel.BeginGetChildren2(
                        promptName1,
                        parameterName1,
                        parameterValue1,
                        callback1,
                        asyncState);
                },
                new object[]
                    {
                        promptName,
                        parameterName,
                        parameterValue
                    },
                result =>
                {
                    try
                    {
                        var retVal = Channel.EndGetChildren2(result);
                        return new object[] { retVal };
                    }
                    catch (Exception exception)
                    {
                        var response = new GetChildrenResponse
                        {
                            ErrorOccured = true,
                            ErrorMessage = exception.Message
                        };
                        return new object[] { response };
                    }
                },
                state =>
                {
                    var args = (InvokeAsyncCompletedEventArgs)state;
                    callback((GetChildrenResponse)args.Results[0]);
                },
                new object());
        }
    }
}
